package com.xiangshizhineng.tianzhangzhi.app.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiangshizhineng.tianzhangzhi.app.common.PagingContext;
import com.xiangshizhineng.tianzhangzhi.app.common.SortingContext;
import com.xiangshizhineng.tianzhangzhi.app.common.base.BaseServiceImpl;
import com.xiangshizhineng.tianzhangzhi.app.common.exception.ServiceException;
import com.xiangshizhineng.tianzhangzhi.app.dao.UserDAO;
import com.xiangshizhineng.tianzhangzhi.app.model.dto.UserDTO;
import com.xiangshizhineng.tianzhangzhi.app.model.entity.User;
import com.xiangshizhineng.tianzhangzhi.app.model.request.LoginRequest;
import com.xiangshizhineng.tianzhangzhi.app.model.response.LoginResponse;
import com.xiangshizhineng.tianzhangzhi.app.model.response.UserResponse;
import com.xiangshizhineng.tianzhangzhi.app.service.UserService;
import com.xiangshizhineng.tianzhangzhi.app.utils.BeanUtil;
import com.xiangshizhineng.tianzhangzhi.app.utils.HttpURLConnectionUtil;
import com.xiangshizhineng.tianzhangzhi.app.utils.JwtUtils;
import com.xiangshizhineng.tianzhangzhi.app.utils.RedisUtils;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.util.*;

@Service
@Slf4j
@Transactional
public class UserServiceImpl extends ServiceImpl<UserDAO, UserResponse> implements UserService {

    @Autowired
    private UserDAO userDAO;
    @Autowired
    private RedisUtils redisUtils;

    @Value("${zhengyuan.addr}")
    private String remote_addr;
    @Value("${zhengyuan.login-url}")
    private String loginUrl;
    @Value("${zhengyuan.get-info-url}")
    private String getInfoUrl;

    /**
     * 用户登录接口
     * @param loginRequest
     * @param request
     * @return
     */
    @Override
    public LoginResponse login(LoginRequest loginRequest, HttpServletRequest request,HttpServletResponse response) throws IOException {
        // 调用正元两个接口
        String token;
        try {
            token = this.getRemoteToken(loginRequest);
            LoginResponse loginResponse = this.getRemoteUserInfo(token);
            // 生成token
            String accessToken = JwtUtils.signApp(loginResponse.getUserId(), loginResponse.getUsername(), loginResponse.getUsername(), redisUtils);
            loginResponse.setToken(accessToken);
            return loginResponse;
        } catch (Exception e) {
//            throw new ServiceException("网络异常");
            return null;
        }

    }


    /**
     * 调用正元接口获取token
     * @param loginRequest
     * @return
     */
    private String getRemoteToken(LoginRequest loginRequest) throws Exception {
        JSONObject params = new JSONObject();
        params.put("username", loginRequest.getUserName());
        params.put("password", loginRequest.getPassword());
        params.put("client_id", "bhyo5ydrhnbg22rc8lcscc1p");
        params.put("client_secret", "o7mpygmo5snttcybbpg5nuzsm9sas0ya");
        params.put("grant_type", "password");

        StringBuilder p = new StringBuilder();
        for (Map.Entry<String, Object> entry : params.entrySet()) {
            p.append(entry.getKey()).append("=").append(URLEncoder.encode(entry.getValue().toString(), "UTF-8")).append("&");
        }
        String loginPath = remote_addr + loginUrl;
        String loginRes;
        try {
            loginRes = HttpURLConnectionUtil.doPostForm(loginPath, p.toString());
        } catch (Exception e) {
            log.error("调用正元登录接口异常: {}, {}", e.getMessage(), e);
            throw new ServiceException("网络异常，请稍后再试");
        }
        log.info("正元登录接口返回报文：{}", loginRes);
        JSONObject loginResult = JSONObject.parseObject(loginRes);
        String tokenType = loginResult.getString("token_type");
        String accessToken = loginResult.getString("access_token");
        String refreshToken = loginResult.getString("refresh_token");
        if (StringUtils.isBlank(tokenType) || StringUtils.isBlank(accessToken)) {
            log.error("正元返回参数异常");
            throw new ServiceException("参数异常");
        }
        return tokenType + " " + accessToken;
    }

    /**
     * 调用正元接口获取token
     * @param loginRequest
     * @return
     */
/*    private String getRemoteToken11(LoginRequest loginRequest) {
        Map<String,String> params = new HashMap<>();
        params.put("username", loginRequest.getUserName());
        params.put("password", loginRequest.getPassword());
        params.put("client_id", "bhyo5ydrhnbg22rc8lcscc1p");
        params.put("client_secret", "o7mpygmo5snttcybbpg5nuzsm9sas0ya");
        params.put("grant_type", "password");
        String loginPath = remote_addr + loginUrl;
        String loginRes;
        try {
            loginRes = HttpURLConnectionUtil.doPostForm11(loginPath, params,params);
        } catch (Exception e) {
            log.error("调用正元登录接口异常: {}, {}", e.getMessage(), e);
            throw new ServiceException("网络异常，请稍后再试");
        }
        log.info("正元登录接口返回报文：{}", loginRes);
        JSONObject loginResult = JSONObject.parseObject(loginRes);
        String tokenType = loginResult.getString("token_type");
        String refreshToken = loginResult.getString("refresh_token");
        if (StringUtils.isBlank(tokenType) || StringUtils.isBlank(refreshToken)) {
            log.error("正元返回参数异常");
            throw new ServiceException("参数异常");
        }
        String token = tokenType + " " + refreshToken;
        return token;
    }*/

    /**
     * 调用正元接口获取用户信息
     * @param token
     * @return
     */
    private LoginResponse getRemoteUserInfo(String token) {
        String getUserInfoPath = remote_addr + getInfoUrl;
        String getInfoRes;
        try {
            getInfoRes = HttpURLConnectionUtil.doGetWithToken(getUserInfoPath, null, token);
            log.info("正元获取用户信息接口返回报文：{}", getInfoRes);
            JSONObject getUserInfoResult = JSONObject.parseObject(getInfoRes);
            JSONObject data = getUserInfoResult.getJSONObject("data");
            JSONObject userInfo = data.getJSONObject("userInfo");
            Long userId = userInfo.getLong("userId");
            String username = userInfo.getString("username");
            LoginResponse loginResponse = new LoginResponse();
            loginResponse.setUserId(userId);
            loginResponse.setUsername(username);
            return loginResponse;
        } catch (Exception e) {
            log.error("调用正元获取用户信息接口异常: {}, {}", e.getMessage(), e);
            throw new ServiceException("网络异常，请稍后再试");
        }

    }

    @Override
    public void logout(String userName, HttpServletRequest request) {
        String tokenKey = "APP_LOGIN_" + userName;
        redisUtils.del(tokenKey);
    }

    @Override
    public List<UserResponse> tbSuperior(String code, String tzjb) {
        return userDAO.tbSuperior(code,tzjb);
    }

    @Override
    public List<UserResponse> selectTZ(@Param(Constants.WRAPPER) Wrapper<UserResponse> wrapper) {
        return userDAO.selectTZ(wrapper);
    }

    @Override
    public UserResponse findUserById(Long id) {
        return userDAO.findUserById(id);
    }
}
